package com.jiufengxinxi.ts.device.equipment.rfid;

import com.gg.reader.api.dal.GClient;
import com.gg.reader.api.dal.HandlerTagEpcLog;
import com.gg.reader.api.dal.HandlerTagEpcOver;
import com.gg.reader.api.protocol.gx.*;
import com.jiufengxinxi.ts.common.utils.JsonUtil;
import com.jiufengxinxi.ts.device.callback.IDeviceStateCallback;
import com.jiufengxinxi.ts.device.interfaces.IReadDevice;
import com.thingmagic.ReaderException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

@Component
public class RfidGXOperate implements IReadDevice, HandlerTagEpcLog, HandlerTagEpcOver {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 客户端
     */
    private GClient client = null;


    /**
     * 天线列表
     */
    private int[] antennaList = null;

    /**
     * 功率
     */
    private int readerPower;

    /**
     * 停止标识
     */
    private MsgBaseStop msgBaseStop = null;

    /**
     * 状态回调
     */
    private IDeviceStateCallback deviceStateCallback = null;


    /**
     * 读卡监听
     */
    private IReadListener readListener = null;

    /**
     * EPC 读取标签
     */
    private MsgBaseInventoryEpc msgBaseInventoryEpc = null;

    /**
     *
     */
    private MsgBaseSetPower msgBaseSetPower = null;

    /**
     * TID 读取标签
     */
    private ParamEpcReadTid tid = null;

    /**
     * 读卡地址
     */
    private String readerAddress = null;

    /**
     * 天线组
     */
    private String[] antennaGroup;

    /**
     * 结果
     */
    private BlockingQueue<String[]> readQue = null;


    private int state;// 0=未初始,1=已经初始，2=监听读卡中,3=读卡中,4=写卡中

    private int readType;

    private boolean checkFlag = false;

    private boolean threadBuilded = false;

    private boolean canReadFlag = true;

    @Override
    public void init() throws Exception {
        logger.info("RFID_GX: 读写器初始化开始："+readerAddress);
        client = new GClient();

        msgBaseStop = new MsgBaseStop();

        msgBaseInventoryEpc = new MsgBaseInventoryEpc();

        tid = new ParamEpcReadTid();

        msgBaseSetPower = new MsgBaseSetPower();

        readQue = new ArrayBlockingQueue<String[]>(2000);


        client.sendSynMsg(new MsgAppReset());

        if(readerAddress.startsWith("tmr://")){
            if(client.openSerial(readerAddress.replace("tmr://",""), 2000)){
                logger.info("RFID_GX: 串口读写器初始化成功");
                state = 1;
            } else{
                logger.info("RFID_GX: 串口读写器初始化失败");
            }
        }

        if(readerAddress.startsWith("socket://")){
            if(client.openTcp(readerAddress.replace("socket://",""), 2000)){
                logger.info("RFID_GX: TCP读写器初始化成功");
                state = 1;
            } else{
                logger.info("RFID_GX: TCP读写器初始化失败");
            }
        }

        if(state==1){
            client.sendSynMsg(msgBaseStop);
        }

        if(!threadBuilded){
            threadBuilded = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        try{
                            if(canReadFlag){
                                while(readQue.size()>0){
                                    String[] readData = readQue.poll();
                                    //logger.info( String.format("RFID_GX:读到卡 %s,%s,%s,%s",readData[0],readData[1],readData[2],readData[3]));
                                    if(readListener!=null){
                                        readListener.tag(readData[0],readData[1],Integer.parseInt(readData[2]),Integer.parseInt(readData[3]));
                                    }
                                }
                            }
                            Thread.sleep(20);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }

        checkFlag = true;

    }

    @Override
    public void init(String readerAddress, String[] antennaGroup, int readerPower) throws ReaderException {
        this.readerAddress = readerAddress;
        this.readerPower = readerPower;
        this.antennaGroup = antennaGroup;
        if(antennaGroup == null) {
            return ;
        }

        List<Integer> antennas=new ArrayList<Integer>();
        for(String as:antennaGroup){
            String[] at=as.split(",");
            for(String a:at){
                antennas.add(Integer.parseInt(a));
            }
        }

        this.antennaList=new int[antennas.size()];
        for(int i=0;i<antennaList.length;i++){
            antennaList[i]=antennas.get(i);
        }

        try {
            init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void log(String s, LogBaseEpcOver logBaseEpcOver) {
        logger.info("RFID_GX:读写器回调1 "+s+"    "+logBaseEpcOver.getRtMsg());
    }

    @Override
    public void log(String s, LogBaseEpcInfo logBaseEpcInfo) {
        //logger.info("RFID_GX:读写器回调2 "+s+"    "+logBaseEpcInfo.getRtMsg());
        readQue.offer(new String[]{logBaseEpcInfo.getTid(),logBaseEpcInfo.getEpc(),
                String.valueOf(logBaseEpcInfo.getAntId()),String.valueOf(logBaseEpcInfo.getRssi())});
    }

    @Override
    public void listen() throws Exception {
        try {
            if (state == 0) {
                return;
            }

            client.onTagEpcLog = this;

            client.onTagEpcOver = this;

            Long antes = null;


            /**
             * 设置功率  ---  开始
             */
            MsgBaseSetPower msgBaseSetPower = new MsgBaseSetPower();
            Hashtable<Integer, Integer> hashtable = new Hashtable<Integer, Integer>();
            logger.info("RFID_GX: 天线："+ JsonUtil.toJson(antennaList));
            for (int annt : antennaList) {
                hashtable.put(annt, readerPower / 100);

                long ant = 0;

                switch (annt) {
                    case 1:
                        ant = EnumG.AntennaNo_1;
                        break;
                    case 2:
                        ant = EnumG.AntennaNo_2;
                        break;
                    case 3:
                        ant = EnumG.AntennaNo_3;
                        break;
                    case 4:
                        ant = EnumG.AntennaNo_4;
                        break;
                }

                if (antes == null) {
                    antes = ant;
                } else {
                    antes = antes | ant;
                }
            }

            msgBaseSetPower.setDicPower(hashtable);
            client.sendSynMsg(msgBaseSetPower);
            /**
             * 设置功率  --- 结束
             */


            msgBaseInventoryEpc.setInventoryMode(EnumG.InventoryMode_Inventory);
            msgBaseInventoryEpc.setAntennaEnable(antes);

            if (readType == 1) {
                tid.setMode(EnumG.ParamTidMode_Auto);
                tid.setLen(6);
                msgBaseInventoryEpc.setReadTid(tid);
            } else {
                msgBaseInventoryEpc.setReadTid(null);
            }

            client.sendSynMsg(msgBaseInventoryEpc);

            logger.info("RFID_GX: 打开读写器监听");

        }finally {
            if (0 == msgBaseInventoryEpc.getRtCode()) {
                state = 2;
            } else {
                state = 1;
            }
        }
    }

    @Override
    public void stopListen() throws Exception {
        try {
            if (state == 0) {
                return;
            }


            logger.info("RFID_GX: 停止读写器监听");

            client.sendSynMsg(msgBaseStop);

            msgBaseInventoryEpc.setReadTid(null);



        }finally {
            state = 1;
        }
    }

    @Override
    public String write(String tag, String targetTag, int antenna) {
        MsgBaseWriteEpc msg = new MsgBaseWriteEpc();

        long ant = 0;

        switch (antenna){
            case 1: ant = EnumG.AntennaNo_1; break;
            case 2: ant = EnumG.AntennaNo_2; break;
            case 3: ant = EnumG.AntennaNo_3; break;
            case 4: ant = EnumG.AntennaNo_4; break;
        }

        msg.setAntennaEnable(ant);

        return null;
    }

    @Override
    public List<String> read() throws Exception {
        try {
            canReadFlag = false;
            listen();
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
            }
            stopListen();
        }finally {
            canReadFlag = false;
            List<String> tags = new ArrayList<String>();

            while(readQue.size()>0){
                String[] readData = readQue.poll();
                logger.info("RFID_GX: 推送卡号 "+readData[0]+" "+readData[1]);
                if(StringUtils.isNotEmpty(readData[0])){
                    tags.add(readData[0]);
                }else{
                    tags.add(readData[1]);
                }
            }

            return tags;
        }
    }

    @Override
    public boolean writePower(int readPower) {
        return false;
    }

    @Override
    public int getReadType() {
        return readType;
    }

    @Override
    public void setReadType(int readType) {
        this.readType = readType;
    }

    @Override
    public int getState() {
        return state;
    }

    @Override
    public String getReaderURI() {
        return readerAddress;
    }

    @Override
    public int[] getAntennaList() {
        return antennaList;
    }

    @Override
    public void setReadListener(IReadListener readListener) {
        this.readListener = readListener;
    }

    @Override
    public String status() {
        return String.valueOf(state);
    }

    @Override
    public boolean check() {
        return checkFlag;
    }

    @Override
    public void destroy() {
        client.close();
        state = 0;
    }

    @Override
    public void startup() {

    }

    @Override
    public String getDeviceName() {
        return "国芯读写器";
    }

    @Override
    public void setDeviceCallback(IDeviceStateCallback deviceCallback) {
        this.deviceStateCallback = deviceCallback;
    }

}
